package com.hsogoo.collate.quartz;


import com.hsogoo.collate.constants.Constant;
import com.hsogoo.collate.domain.CollateConfig;
import com.hsogoo.collate.domain.CollateRecord;
import com.hsogoo.collate.mapper.CollateRecordMapper;
import com.hsogoo.collate.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.batch.core.*;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 对账job启动器
 * 用来启动对账的SpringBatch job
 * @Author huangsaigang
 * Created @2019-10-28.
 */
@Slf4j
@Service
public class CollateJobLauncher extends QuartzJobBean {

    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    private Job batchCollateJob;
    @Autowired
    private CollateRecordMapper collateRecordMapper;
    @Value("${app.local.filepath}")
    private String localFilePath;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        String jobName = jobExecutionContext.getJobDetail().getKey().getName();
        log.info("[{}] is running...", jobName);
        CollateConfig collateConfig = (CollateConfig)jobExecutionContext.getJobDetail().getJobDataMap().get(Constant.DEFAULT_PARAMS_KEY);
        //目标对账日期
        Date targetCollateDate = DateUtil.addDays(new Date(), Integer.valueOf(String.valueOf(0 - collateConfig.getCollateDays())));
        String targetCollateDateString = DateUtil.getDateString(targetCollateDate, "yyyyMMdd");
        //目标对账文件地址
        String targetCollateFile = String.format(collateConfig.getTargetFilePath(), targetCollateDateString);
        //验证入参
        if(isExecutedJob(jobName, targetCollateDateString, targetCollateFile)){
            log.warn("已执行过的jobName[{}],filePath[{}]", jobName, targetCollateFile);
            return;
        }
        String localFilePath = createLocalFullFileName(targetCollateDateString, targetCollateFile);
        //启动SpringBatch任务
        Map<String, JobParameter> jobParameterMap = getJobParameters(collateConfig);
        //已经转化好，后面直接用，不用再次转换了
        jobParameterMap.put("targetCollateDate", new JobParameter(targetCollateDateString));
        jobParameterMap.put("targetCollateFile", new JobParameter(targetCollateFile));
        jobParameterMap.put("localFilePath", new JobParameter(localFilePath));
        jobParameterMap.put("runTime", new JobParameter(System.currentTimeMillis()));
        JobParameters jobParameters = new JobParameters(jobParameterMap);
        JobExecution jobExecution = null;
        try {
            jobExecution = jobLauncher.run(batchCollateJob, jobParameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(jobExecution != null){
            if (BatchStatus.COMPLETED != jobExecution.getStatus()) {
                throw new RuntimeException("exception...");
            }
        }

    }

    private String createLocalFullFileName(String collateDate, String targetCollateFile){
        int position = targetCollateFile.lastIndexOf("/");
        String fileName = targetCollateFile.substring(position);
        String localFileName = localFilePath + collateDate + fileName;
        return localFileName;
    }

    /**
     * 是否是执行过的job
     * 以下3个入参为唯一键
     * @param taskName
     * @param collateDate
     * @param collateFile
     * @return
     */
    private boolean isExecutedJob(String taskName, String collateDate, String collateFile) {
        CollateRecord collateRecord = collateRecordMapper.getCollateRecord(taskName, collateDate, collateFile);
        if (collateRecord == null) {
            return false;
        }
        return true;
    }

    private Map<String, JobParameter> getJobParameters(CollateConfig collateConfig){
        Map<String, JobParameter> parameters = new HashMap<>();
        Field[] fields = collateConfig.getClass().getDeclaredFields();
        if(fields != null && fields.length > 1){
            for(Field field : fields){
                field.setAccessible(true);
                try {
                    if(field.getType() == String.class) {
                        parameters.put(field.getName(), new JobParameter((String)field.get(collateConfig)));
                    }else if(field.getType() == Long.class) {
                        parameters.put(field.getName(), new JobParameter((Long) field.get(collateConfig)));
                    }
                } catch (IllegalAccessException e) {
                    log.error("{} can not access", field.getName());
                }
            }
        }
        return parameters;
    }

}
